#ifndef HASH_H
#define HASH_H
#include "ListaAsoc.h"

typedef struct sHash * Hash;

/* constructor:
 PRE:{True}
    h = hash_empty()
 POS:{(h->cantelem = 0) ^ (h->arr)[i]=la_empty() ^ 0 <= i < TAM_HASH-1}
*/
Hash
hash_empty (void);

/* agrega una clave y un dato
 PRE:{h = H ^ H!=NULL ^ h->cantelem=n ^ k=K ^ d=D ^ k!=NULL ^ d!=NULL}
     hash_add(h,k,d)
 POS:{ k=K ^ d=D ^ h->cantelem=n+1 ^ ((h->arr)[f_hash(k)])[j]=(K,D)
   ^ j=((h->arr)[f_hash(k)])->tam } 
*/
void
hash_add (Hash h, Key k, Data d);

/* devuelve si existe la clave en el hash
 PRE:{h=H  ^ k=K }
   b=hash_exists(h,k)
 POS:{h=H ^ k=K ^ (b => < E i,j : 0<=i<((h->arr[j])->tam) ^ j=f_hash(k) : tuple_fst(((h->arr)[j])[i])=K > ) } 
*/
Bool
hash_exists (Hash h, Key k);

/* busca un dato segun la clave
   debe llamarse solo si hash_exists (l, k)
   ¡ no lo encuentra devuelve NULL¡???
 PRE:{h=H ^ k=K }
  d=hash_search(h,k)
 POS:{h=H ^ k=K ^ < E i,j : 0<=i<((h->arr[j])->tam) 
       ^ j=f_hash(k) : d=tuple_snd((h->arr)[j])[i] > } 
*/
Data
hash_search (Hash h, Key k);


/* borra la clave y el valor asociado 
PRE:{h=H ^ k=K}
hash_del (Hash h, Key k)
POS:{k=K ^ H - {(k,...)} = h}
*/
void
hash_del (Hash h, Key k);

/* devuelve la cantidad de elementos 
	PRE:{h != NULL}
	i=hash_length(h);
	POS:{i = (h -> cantelem) } 
*/
int
hash_length (Hash h);

/* Lee un hash desde un archivo
	PRE:{nomfile != ""}
	h=hash_fromFile(nomfile) */
Hash
hash_fromFile(char *nomfile);

/* Graba un hash a un archivo*/
void
hash_toFile(char *nomfile, Hash h);

/* Destructor.
   Destruye la tabla y su contenido */
Hash
hash_destroy(Hash h);

void hash_pprint(Hash h);

/*Devuelve el código hash de clave
	PRE:{True}
	c=f_hash(k)
	POS:{c=<Ʃ i :0<=i<(k -> size):toascii((k -> clave)[i])>%T}
	(Donde T es un entero primo a elegir)  */
int
f_hash(Key k);  /* <-- Esta función es interna al Hash => NO DEBERIA SER EXPORTADA */

float
media (Hash h);

float
varianza (Hash h);

#endif
